/**
 *
 */
package pers.vic.blog.module.api.task.service;

import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
import pers.vic.blog.module.api.task.model.BlogTaskJob;
import pers.vic.boot.base.vo.BooleanWithMsg;


/**
 *  @description: 定时任务工具类
 *  @author Vic.xu
 *  @date: 2020年8月28日下午5:04:40
 */
@Component
public class QuartzManagerService {
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    private static Logger logger = LoggerFactory.getLogger(QuartzManagerService.class);

    /**
     * 添加任务，触发器组同任务组
     */
    public BooleanWithMsg addJob(BlogTaskJob info) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();

            JobKey jobKey = JobKey.jobKey(info.getCode(), info.getGroup());
            if (exist(info)) {
                logger.info("{}， {} 定时任务已经存在", info.getCode(), info.getGroup());
                return BooleanWithMsg.False("定时任务已经存在");
            }

            JobDataMap map = new JobDataMap();
            map.put("remark", info.getRemark());

            // JobDetail 是具体Job实例
            JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(info.getClazz()))
                    .withIdentity(info.getCode(), info.getGroup())
                    .usingJobData(map)
                    .build();

            // 基于表达式构建触发器
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(info.getCron());
            // CronTrigger表达式触发器 继承于Trigger
            // TriggerBuilder 用于构建触发器实例
            CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(info.getCode() + "_trigger", info.getGroup())
                    .withSchedule(cronScheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, cronTrigger);

            //启动
            if (!scheduler.isShutdown()) {
                scheduler.start();
            }
            return BooleanWithMsg.True();
        } catch (SchedulerException | ClassNotFoundException e) {
            logger.error("添加任务失败", e);
            return BooleanWithMsg.False("添加任务失败");
        }
    }

    /**
     * 暂停任务
     * @param info
     */
    public BooleanWithMsg pauseJob(BlogTaskJob info) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            JobKey jobKey = JobKey.jobKey(info.getCode(), info.getGroup());
            scheduler.pauseJob(jobKey);
            logger.info("pause job: {} success", info.getCode());
            return BooleanWithMsg.True();
        } catch (Exception e) {
            logger.error("暂停任务失败{}", e);
            return BooleanWithMsg.False("暂停任务失败{}");
        }
    }

    /**
     * 恢复任务
     */
    public BooleanWithMsg resumeJob(BlogTaskJob info) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            JobKey jobKey = JobKey.jobKey(info.getCode(), info.getGroup());
            scheduler.resumeJob(jobKey);
            logger.info("=========================resume job: {} success========================", info.getCode());
            return BooleanWithMsg.True();
        } catch (Exception e) {
            logger.error("运行任务失败{}", e);
            return BooleanWithMsg.False("运行任务失败{}");

        }
    }

    /**
     * 判断是否存在任务
      * @param info
     * @return
     */
    public boolean exist(BlogTaskJob info){
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();

            JobKey jobKey = JobKey.jobKey(info.getCode(), info.getGroup());
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            return jobDetail != null;
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 立刻执行
     */
    public BooleanWithMsg runJobNow(BlogTaskJob info) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            JobKey jobKey = JobKey.jobKey(info.getCode(), info.getGroup());
            scheduler.triggerJob(jobKey);
            logger.info("=========================runJob Now : {} success========================", info.getCode());
            return BooleanWithMsg.True();
        } catch (Exception e) {
            logger.error("立即运行任务失败{}", e);
            return BooleanWithMsg.False("立即运行任务失败");

        }
    }

    /**
     * 删除任务，在业务逻辑中需要更新库表的信息
     * @param info
     * @return
     */
    public BooleanWithMsg removeJob(BlogTaskJob info) {
        try {
            boolean result = false;
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            JobKey jobKey = JobKey.jobKey(info.getCode(), info.getGroup());
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            if (null != jobDetail) {
                result = scheduler.deleteJob(jobKey);
            }
            logger.info("=========================remove job: {} {}========================", info.getCode(), result);
            if (result) {
                return BooleanWithMsg.True();
            }
        } catch (Exception e) {
            logger.error("", e);
        }
        return BooleanWithMsg.False("删除任务失败");
    }

    /**
     * 修改定时任务的时间
     */
    public boolean modifyJobTime(BlogTaskJob info) {
        boolean result = true;
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(info.getCode() + "_trigger", info.getGroup());
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            String oldTime = trigger.getCronExpression();
            if (!StringUtils.equalsIgnoreCase(oldTime, info.getCron())) {
                CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(info.getCron());
                //+ RandomStringUtils.randomAlphabetic(6)
                CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(info.getCode()  + "_trigger", info.getGroup())
                        .withSchedule(cronScheduleBuilder)
                        .build();

                scheduler.rescheduleJob(triggerKey, cronTrigger);
                scheduler.resumeTrigger(triggerKey);
            }

        } catch (Exception e) {
            logger.error("修改定时任务的时间失败", e);
            result = false;
        }
        return result;
    }

    /**
     * 启动所有定时任务
     */
    public boolean startJobs() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            scheduler.start();
            return true;
        } catch (SchedulerException e) {
            logger.error("启动所有定时任务失败", e);
        }
        return false;
    }

    /**
     * 停止所有任务
     */
    public void shutdownJobs() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            if (!scheduler.isShutdown()) {
                scheduler.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

